app.directive('csAddress', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            csAddress: '=ngModel'
        },
        link: function (scope, elem, attrs) {

        },
        controller: ['$scope','$http', function ($scope, $http) {
            $scope.address = { province: '', city: '', district: '', detail: '' };
            $http.get('./templates/address.json').success(function (data) {
                $scope.address.data = data;
                $scope.address.provinces = Object.keys($scope.address.data);
                angular.forEach($scope.address.provinces, function (p) {
                    $scope.address.data[p].citys = Object.keys($scope.address.data[p]);
                    
                });
            });
            

            $scope.detail = function (d) {
                if (d || d == '') {
                    $scope.address.detail = d;
                    setValue();
                } else {
                    getValue('detail', 3);
                    return $scope.address.detail;
                }
            };
            $scope.province = function (d) {
                if (d) {
                    if ($scope.address.province != d) {
                        $scope.address.province = d;
                        $scope.address.city = '';
                        $scope.address.district = '';
                        setValue();
                    }
                } else {
                    getValue('province', 0);
                    return $scope.address.province;
                }
            };
            $scope.city = function (d) {
                if (d ) {
                    if ($scope.address.city != d) {
                        $scope.address.city = d;
                        $scope.address.district = '';
                        setValue();
                    }
                } else {
                    getValue('city', 1);
                    return $scope.address.city;
                }
            };
            $scope.district = function (d) {
                if (d) {
                    $scope.address.district = d;
                    setValue();
                } else {
                    getValue('district', 2);
                    return $scope.address.district;
                }
            };

            var setValue = function () {
               // $scope.csAddress = '{province}-{city}-{district}-{detail}'.format($scope.address);
                setModelValue('{province}-{city}-{district}-{detail}'.format($scope.address));
            }
            var getValue = function (attr, index) {
                var tmpValue = getModelValue();
                if (angular.isUndefined(tmpValue) || tmpValue == null) return;
                if (tmpValue != '') {
                    var array = tmpValue.split('-');
                    if (array.length !== 4) {
                        if (attr === "detail") {
                            $scope.address.province = tmpValue;
                        }
                        return;
                    }
                    $scope.address[attr] = array[index];
                } else {
                    $scope.address[attr] = '';
                }
            }
            var getModelValue = function () {
                if ($scope.csAddress) {
                    var modelValue = 0;
                    if (angular.isFunction($scope.csAddress)) {
                        modelValue = $scope.csAddress();
                    } else {
                        modelValue = $scope.csAddress;
                    }
                    return modelValue;
                }
                return null;
            }
            var setModelValue = function (d) {
                if (angular.isFunction($scope.csAddress)) {
                    $scope.csAddress(d);
                }
                else {
                    $scope.csAddress = d;
                }
            }
        }],
        templateUrl:'./templates/address.html'
    };
}]);

app.directive('csCountry', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            csCountry: '=ngModel'
        },
        link: function (scope, elem, attrs) {

        },
        controller: ['$scope', '$http', function ($scope, $http) {
            $scope.countries = [];
            $http.get('./templates/country.json').success(function (data) {
                angular.forEach(Object.keys(data), function (p) {
                    $scope.countries.push(data[p]);
                });
            });

            $scope.country = function (d) {
                if (d) {
                    $scope.csCountry = d;
                } else {
                    return $scope.csCountry;
                }
            };
            
        }],
        templateUrl: './templates/country.html'
    };
}]);


app.directive('csValidate', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        require: 'ngModel',
        
        link: function (scope, elem, attrs, ctrl) {
            var validateExpression = attrs.csValidate;
            var validate;
            scope.$watch(function () {
                validate = $parse(validateExpression)(scope);
                if (!angular.isDefined(validate)) { validate = false;}
                return validate;
            }, function () {
                //var v = $parse(validateExpression)(scope);
                ctrl.$setValidity('csValidate', validate);
            });
        }
    };
}]);

app.directive('csValidates', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        require: 'ngModel',

        link: function (scope, elem, attrs, ctrl) {
            
            var validateExpression = attrs.csValidates;
            var validate;
            scope.$watch(function () {
                validate = $parse(validateExpression)(scope);
                var watch = '';
                angular.forEach(Object.keys(validate), function (key) {
                    if (!angular.isDefined(validate[key])) { validate[key] = false; }
                    watch += validate[key];
                });
                return watch;
            }, function () {
                //var v = $parse(validateExpression)(scope);
                angular.forEach(Object.keys(validate), function (key) {
                    ctrl.$setValidity(key, validate[key]);
                });
            });
        }
    };
}]);


app.directive('convertToNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            if (attrs.convertToNumber && attrs.convertToNumber == 'true') {
                ngModel.$parsers.push(function (val) {
                    return parseInt(val, 10);
                });
                ngModel.$formatters.push(function (val) {
                    return '' + val;
                });
            }
        }
    };
});

app.directive('icheck', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        require:'ngModel',
        link: function ($scope, element, $attrs, ngModel) {
            return $timeout(function () {
                var value;
                value = $attrs['value'];
                if ($attrs.ngModel) {
                    $scope.$watch($attrs['ngModel'], function (newValue) {
                        $(element).iCheck('update');
                    })
                }

                return $(element).iCheck({
                    checkboxClass: 'icheckbox_minimal',
                    radioClass: 'iradio_minimal',
                    indeterminateClass: 'icheckbox_futurico'
                    

                }).on('ifChanged', function (event) {
                    if ($attrs.ngModel) {
                        if ($(element).attr('type') === 'checkbox' && $attrs['ngModel']) {
                            $scope.$apply(function () {
                                return ngModel.$setViewValue(event.target.checked);
                            });
                        }
                        if ($(element).attr('type') === 'radio' && $attrs['ngModel']) {
                            return $scope.$apply(function () {
                                return ngModel.$setViewValue(value);
                            });
                        }
                    }
                }).on('click', function (event) {
                    
                });
            });
        }
    };
}]);


app.directive('csSelectAll', ['$rootScope', '$parse', function ($rootScope, $parse) {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function (scope, elem, attrs, ngModel) {
            $(elem).html('<input type="checkbox" id="select_all" />');
            var selecteds = $parse(attrs.ngModel)(scope);
            scope.$watch(attrs.ngModel, function (newValue) {
                //var selecteds = newValue;
                var checked = 0, unchecked = 0;
                var propKeys = Object.keys(selecteds.items);
                var action;
                angular.forEach(propKeys, function (key) {
                    if (selecteds.items[key]) {
                        checked += 1;
                    } else {
                        unchecked += 1;
                    }
                });
                if ((unchecked == 0) || (checked == 0)) {
                    action = (checked == propKeys.length) && propKeys.length > 0 ? 'check' : (propKeys.length > 1 ? 'determinate' : 'uncheck');
                    //action = 'determinate';
                } else {
                    action = 'indeterminate';
                }

                $(elem).find('input').iCheck(action);

            }, true);
            return $(elem).find('input').iCheck({
                checkboxClass: 'icheckbox_minimal',
                radioClass: 'iradio_minimal',
                indeterminateClass: 'icheckbox_futurico'
            }).on('ifClicked', function (event) {
                var propKeys = Object.keys(selecteds.items);
                angular.forEach(propKeys, function (key) {
                    selecteds.items[key] = !event.target.checked;
                });
                scope.$apply(function () {
                    return ngModel.$setViewValue(selecteds);
                });
            })
        }
        
    };
}]);

app.directive('csPortlet', ['$rootScope', '$compile', '$ocLazyLoad', function ($rootScope, $compile, $ocLazyLoad) {

    return {
        restrict: 'A',
        scope: {

        },
        link: function (scope, elem, attrs) {
            //$ocLazyLoad.load({
            //    name: 'MainApp',
            //    files: [
            //         'js/controllers/Portlets/demo1.js'
            //    ]
            //}).then(function () {
            //    var angularBackgroundDomEl = angular.element('<div ng-controller="demo1" ng-init="Title=1;">sdfdsfdsfdsfdsfdsf{{Title}}</div><button ng-click="test()">test</button>');
            //    $(elem).append($compile(angularBackgroundDomEl)($rootScope.$new(true)));
            //});
        },
        //template:"loading..."
        templateUrl: function (elem, attrs) {
            return "portlets/" + attrs.csPortlet + ".html";
        }

    };
}]);
app.directive('csDatepicker', ['$rootScope', '$parse', '$filter', function ($rootScope, $parse, $filter) {
    return {
        restrict: 'E',
        require: '?ngModel',
        scope:true,
        link: function ($scope, elem, attrs, ctrl) {
            if (attrs.minDate) {
                $(elem).find('.input-group').attr('data-date-start-date', attrs.minDate);
            }
            if (attrs.maxDate) {
                $(elem).find('.input-group').attr('data-date-end-date', attrs.maxDate);
            }
            if (attrs.viewMode) {
                $(elem).find('.input-group').attr('data-date-min-view-mode', attrs.viewMode);
            }
            if (attrs.dateFormat) {
                //$(elem).find('.input-group').attr('data-date-format', attrs.dateFormat);
                $scope.dateFormat = attrs.dateFormat;
            }
            if (attrs.ngChange) {
                $(elem).find('input').attr('ng-change', attrs.ngChange);
            }
            if (attrs.name) {
                $(elem).find('input').attr('name', attrs.name);
                if (attrs.required) {
                    $(elem).find('input').attr('required', true);
                }
                if (attrs.csValidate) {
                    $(elem).find('input').attr('cs-validate', attrs.csValidate);
                }
                if (attrs.csValidates) {
                    $(elem).find('input').attr('cs-validates', attrs.csValidates);
                }
            }
            if (!$scope.dateFormat) $scope.dateFormat = "yyyy-MM-dd";

            var datePicker = $(elem).find('.input-group').datepicker({
                language: 'zh-CN',
                rtl: App.isRTL(),
                orientation: "left",
                autoclose: true,
                //datesDisabled: [function (date) {
                //    if (attrs.csDatapickerDisabledMode) {
                //        var today = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0);
                //        switch (attrs.csDatapickerDisabledMode) {
                //            case "GtToday":
                //                return date.valueOf() > now.valueOf() ? 'disabled' : '';
                //                break;
                //            default: return '';
                //        }
                //    }
                //}]
            }).on('changeDate', function (e) {
                if (attrs.ngChange) {
                    $parse(attrs.ngChange)($scope);
                }
            });



            $scope.dateModel = function () {
                if (arguments && arguments.length > 0) {
                    if (arguments[0] == '') {

                    } else {
                        ctrl.$setViewValue(moment(arguments[0]).toDate());
                    }
                } else {
                    if (ctrl.$viewValue) {
                        if (!(ctrl.$viewValue instanceof Date)) {
                            ctrl.$setViewValue(moment(ctrl.$viewValue).toDate());
                        }
                        return $filter('date')(ctrl.$viewValue, $scope.dateFormat);
                    }
                }
            };

        },
        template: '<div class="input-group date date-picker" data-date-format="yyyy-mm-dd" data-date-view-mode="years" data-date-min-view-mode="days">'
                            + '<input type="text" ng-model="dateModel" ng-model-options="{getterSetter: true }" class="form-control" readonly >'
                            + '<span class="input-group-btn">'
                            + ' <button class="btn default" type="button"><i class="fa fa-calendar"></i></button>'
                            + '</span>'
                            + '</div>'
    };
}]);
app.directive('csDatetimepicker', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return {
        restrict: 'E',
        require: '?ngModel', scope: true,
        link: function ($scope, elem, attrs, ctrl) {
            if (attrs.minDate) {
                $(elem).find('.input-group').attr('data-date-start-date', attrs.minDate);
            }
            if (attrs.maxDate) {
                $(elem).find('.input-group').attr('data-date-end-date', attrs.maxDate);
            }
            if (attrs.name) {
                $(elem).find('input').attr('name', attrs.name);
                if (attrs.required) {
                    $(elem).find('input').attr('required', true);
                }
                if (attrs.csValidate) {
                    $(elem).find('input').attr('cs-validate', attrs.csValidate);
                }
                if (attrs.csValidates) {
                    $(elem).find('input').attr('cs-validates', attrs.csValidates);
                }
            }

            $(elem).find('.input-group').datetimepicker({
                autoclose: true,
                isRTL: App.isRTL(),
                format: "yyyy-mm-dd hh:ii",
                pickerPosition: (App.isRTL() ? "bottom-right" : "bottom-left")
            });

            $scope.dateModel = function () {
                if (arguments && arguments.length > 0) {
                    ctrl.$setViewValue(new Date(arguments[0]));
                } else {
                    if (ctrl.$viewValue) {
                        if (!(ctrl.$viewValue instanceof Date)) {
                            ctrl.$setViewValue(new Date(ctrl.$viewValue));
                        }
                        return $filter('date')(ctrl.$viewValue, 'yyyy-MM-dd HH:mm');
                    }
                }
            };

        },
        template: '<div class="input-group date form_datetime">'
									+ '<input type="text" ng-model="dateModel" ng-model-options="{getterSetter: true }" readonly class="form-control">'
									+ '<span class="input-group-btn">'
									+ '<button class="btn default date-set" type="button"><i class="fa fa-calendar"></i></button>'
									+ '</span>'
								+ '</div>'
    };
}]);
app.directive('csMonthpicker', ['$rootScope', '$parse', '$filter', function ($rootScope, $parse, $filter) {
    return {
        restrict: 'E',
        require: '?ngModel', scope: true,
        link: function ($scope, elem, attrs, ctrl) {
            if (attrs.minDate) {
                $(elem).find('.input-group').attr('data-date-start-date', attrs.minDate);
            }
            if (attrs.maxDate) {
                $(elem).find('.input-group').attr('data-date-end-date', attrs.maxDate);
            }
            if (attrs.viewMode) {
                $(elem).find('.input-group').attr('data-date-min-view-mode', attrs.viewMode);
            }
            if (attrs.dateFormat) {
                //$(elem).find('.input-group').attr('data-date-format', attrs.dateFormat);
                $scope.dateFormat = attrs.dateFormat;
            }
            if (attrs.ngChange) {
                $(elem).find('input').attr('ng-change', attrs.ngChange);
            }
            if (attrs.name) {
                $(elem).find('input').attr('name', attrs.name);
                if (attrs.required) {
                    $(elem).find('input').attr('required', true);
                }
                if (attrs.csValidate) {
                    $(elem).find('input').attr('cs-validate', attrs.csValidate);
                }
                if (attrs.csValidates) {
                    $(elem).find('input').attr('cs-validates', attrs.csValidates);
                }
            }
            if (!$scope.dateFormat) $scope.dateFormat = "yyyy-MM";

            $(elem).find('.input-group').datepicker({
                language: 'zh-CN',
                rtl: App.isRTL(),
                orientation: "left",
                autoclose: true,
                //datesDisabled: [function (date) {
                //    if (attrs.csDatapickerDisabledMode) {
                //        var today = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0);
                //        switch (attrs.csDatapickerDisabledMode) {
                //            case "GtToday":
                //                return date.valueOf() > now.valueOf() ? 'disabled' : '';
                //                break;
                //            default: return '';
                //        }
                //    }
                //}]
            }).on('changeDate', function (e) { if (attrs.ngChange) { $parse(attrs.ngChange)($scope); } });



            $scope.dateModel = function () {
                if (arguments && arguments.length > 0) {
                    ctrl.$setViewValue(new Date(arguments[0]));
                } else {
                    if (ctrl.$viewValue) {
                        if (!(ctrl.$viewValue instanceof Date)) {
                            ctrl.$setViewValue(new Date(ctrl.$viewValue));
                        }
                        return $filter('date')(ctrl.$viewValue, $scope.dateFormat);
                    }
                }
            };

        },
        template: '<div class="input-group date date-picker" data-date-format="yyyy-mm" data-date-view-mode="years" data-date-min-view-mode="months">'
                            + '<input type="text" ng-model="dateModel" ng-model-options="{getterSetter: true }" class="form-control" readonly >'
                            + '<span class="input-group-btn">'
                            + ' <button class="btn default" type="button"><i class="fa fa-calendar"></i></button>'
                            + '</span>'
                            + '</div>'
    };
}]);
app.directive('csTemplate', ['$rootScope', '$compile', '$parse', '$ocLazyLoad', '$q', '$templateRequest', '$controller', '$injector', function ($rootScope, $compile, $parse, $ocLazyLoad, $q, $templateRequest, $controller, $injector) {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            scope.$csTemplates = scope.$csTemplates || {
            };


            var templateValue = attrs.csTemplate;
            templateValue = templateValue.toLowerCase().trimStringRight('.html');
            var name = templateValue.trimStringLeft('/').replace(/\//g, '_');
            var csTemplate = function (url, csData, element) {
                var that = this;
                var loaded = false;
                this.reload = function () {
                    loaded = false;
                    this.load();
                };
                this.load = function () {
                    if (loaded) { return; };

                    var templateUrl = $rootScope.settings.getViewUrl(url + '.html');
                    var ctrl = name + '_controller';
                    var data = {};
                    if (csData) {
                        data = $parse(csData)(scope);
                    }
                    var resolve = {
                        data: function () {
                            return data;
                        },
                        deps: ['$ocLazyLoad', function ($ocLazyLoad) {
                            return $ocLazyLoad.load({
                                name: 'MainApp',
                                files: [
                                     Util.versionUrl("js/controllers/" + url + '.js')
                                ]
                            });
                        }]
                    };

                    var templateAndResolvePromise = $q.all([$templateRequest(templateUrl)].concat(getResolvePromises(resolve)));
                    var promiseChain = null;
                    var samePromise = promiseChain = $q.all([promiseChain])
                      .then(function () { return templateAndResolvePromise; }, function () { return templateAndResolvePromise; })
                      .then(function resolveSuccess(tplAndVars) {
                          var modalScope = $rootScope.$new();
                          var ctrlInstance, ctrlLocals = {};
                          var resolveIter = 1;
                          if (ctrl) {
                              ctrlLocals.$scope = modalScope;

                              angular.forEach(resolve, function (value, key) {
                                  ctrlLocals[key] = tplAndVars[resolveIter++];
                              });

                              ctrlInstance = $controller(ctrl, ctrlLocals);
                              element.html($compile(tplAndVars[0])(modalScope));
                              loaded = true;
                              that.scope = modalScope;
                              modalScope.$emit('$viewContentLoaded');
                          }
                      });
                };


                function getResolvePromises(resolves) {
                    var promisesArr = [];
                    angular.forEach(resolves, function (value) {
                        if (angular.isFunction(value) || angular.isArray(value)) {
                            promisesArr.push($q.when($injector.invoke(value)));
                        } else if (angular.isString(value)) {
                            promisesArr.push($q.when($injector.get(value)));
                        } else {
                            promisesArr.push($q.when(value));
                        }
                    });
                    return promisesArr;
                }
            };
            scope.$csTemplates[name] = new csTemplate(templateValue, attrs.csData, elem);


            if (attrs.csDelay && attrs.csDelay == 'true') {

            } else {
                scope.$csTemplates[name].load();
            }

        },

    };
}]);
app.directive('csTree', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        link: function (scope, element, attrs) {
            var isInit = false;
            scope.$watch(attrs.csTree, function () {
                var tree = $parse(attrs.csTree)(scope);
                if (tree) {
                    if (isInit) {
                        $(element).jstree('destroy');
                    }
                    $(element).jstree(tree.option).on("changed.jstree", function (e, data) {
                        if (tree.change) {
                            tree.change(data);
                        }
                    }).on("loaded.jstree", function (e, data) {
                        if (tree.loaded) {
                            tree.loaded(data);
                        }
                    });
                    isInit = true;
                }
            });
            return;
        }
    };
}]);
app.directive('csFile', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            csFileId: '=ngModel'
        },
        link: function (scope, elem, attrs) {
            if (attrs.required) {
                scope.required = true;
            }
            if (attrs.accept) {
                scope.accept = attrs.accept;

            }
            if (attrs.readonly == 'true') {
                scope.readonly = true;
            } else {
                scope.readonly = false;
            }
            if (attrs.multiple == 'true') {
                scope.multiple = true;
            } else {
                scope.multiple = false;
            }
        },
        controller: ['$rootScope', '$scope', '$http', 'FileUploader', function ($rootScope, $scope, $http, FileUploader) {
            var uploader = $scope.uploader = new FileUploader({
                url: $rootScope.settings.getCtrlRouter('', 'fileupload', 'upload'),
                autoUpload: true
            });
            var oriFileId = $scope.csFileId;
            uploader.filters.push({
                name: 'customFilter',
                fn: function (item, options) {
                    return this.queue.length < 10;
                }
            });

            var getFileIds = function () {
                if ($scope.multiple) {
                    var ids = "";
                    for (var i = 0; i < $scope.files.length; i++) {
                        if (i != $scope.files.length - 1) {
                            ids += $scope.files[i].Id + ',';
                        } else {
                            ids += $scope.files[i].Id;
                        }
                    }
                    return ids;
                } else {
                    return $scope.files.length > 0 ? $scope.files[0].Id : 0;
                }
            };

            $scope.files = [];

            $scope.$watch('csFileId', function () {
                if (angular.isDefined($scope.csFileId) && $scope.csFileId != '' && $scope.csFileId != 0) {
                    var oldIds = getFileIds();
                    if (oldIds != $scope.csFileId) {
                        $rootScope.settings.post(['', 'fileupload', 'GetFiles'], $scope.csFileId, function (data) {
                            $scope.files = data;
                        });
                    }
                } else {
                    $scope.files = [];
                }
            });



            $scope.uploader.onSuccessItem = function (fileItem, data, status, headers) {
                if ($scope.multiple) {
                    angular.forEach(data, function (f) {
                        $scope.files.push(f);

                    });
                } else {
                    $scope.files = [];
                    $scope.files.push(data[0]);
                }

                $scope.csFileId = getFileIds();
            };

            $scope.downloadUrl = function (f) {
                return $rootScope.settings.getFileUrl(f.Id);
            };

            $scope.isPicture = function (file) {
                var imgs = ["gif", "ief", "jpeg", "jpg", "jpe", "pcx", "png", "svg", "svgz", "tiff", "tif", "djvu", "djv", "wbmp", "cr2", "crw", "ras",
                      "cdr", "pat", "cdt", "erf", "ico", "art", "jng", "bmp", "nef", "orf", "psd", "pnm", "pbm", "pgm", "ppm", "rgb", "xbm", "xpm", "xwd"];
                if (imgs.indexOf(file.FileType.toLowerCase()) > -1) {
                    return true;
                }
                return false;
            };

            $scope.delete = function (f) {
                if (!oriFileId || oriFileId.indexOf(f.Id) === -1) {
                    $rootScope.settings.post(['', 'fileupload', 'Delete'], f.Id, function (data) {
                        if ($scope.multiple) {
                            var index = $scope.files.indexOf(f);
                            $scope.files.splice(index, 1);
                        } else {
                            $scope.files = [];
                        }
                    });
                }
                else {
                    if ($scope.multiple) {
                        var index = $scope.files.indexOf(f);
                        $scope.files.splice(index, 1);
                    } else {
                        $scope.files = [];
                    }
                }


                $scope.csFileId = getFileIds();
            };

        }],
        templateUrl: './templates/fileUpload.html'
    };
}]);

app.directive('csParameter', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            csModel:'=ngModel',
            csClassCode:'@csClass',
            csReadonly: '=ngReadonly',
            multiple: '=multiple',
            ngRequired: '=ngRequired',
            csContainAllItems:'@csContainAllItems'
        },
        link: function (scope, elem, attrs) {
            scope.valueField = attrs.csValueField;
            
           // scope.csModel = ngModel;
            if (!scope.valueField) scope.valueField = "IntId";

            scope.csContainAllItems = false;
            if (attrs.csContainAllItems) scope.csContainAllItems = true;

            if (attrs.name) {
                $(elem).find('#csperiod_select_input').attr('name', attrs.name);
                if (attrs.required) {
                    $(elem).find('input').attr('required', true);
                }
                if (attrs.csValidate) {
                    $(elem).find('input').attr('cs-validate', attrs.csValidate);
                }
                if (attrs.csValidates) {
                    $(elem).find('input').attr('cs-validates', attrs.csValidates);
                }
                if (attrs.ngDisabled) {
                    $(elem).find('ui-select').attr('ng-disabled', attrs.ngDisabled);
                }
            }
        },
        controller: ['$scope', '$http', function ($scope, $http) {
            //$scope.parameterClass = {};
            //$scope.data = [];
            $scope.text = "";
            var SetText = function (data) {
                var items = data.Data;
                if ($scope.csContainAllItems) {
                    items = angular.copy(data.Data);
                    items.splice(index, 0, {IntId:0,Text:"全部",StringId:""});
                }

                if ($scope.csModel) {
                    for (var i = 0; i < items.length; i++) {
                        if (items[i][$scope.valueField] === $scope.csModel) {
                            $scope.text = items[i].Text;
                            break;
                        }
                    }
                }
                $scope.data = items;
            };
            $scope.$watch("csModel", function () {
                init();
            })
            var init = function () {
                if (!$rootScope.Parameters) { $rootScope.Parameters = {}; }
                if ($rootScope.Parameters[$scope.csClassCode]) {
                    var data = $rootScope.Parameters[$scope.csClassCode];
                    $scope.parameterClass = data.Class;                    
                    SetText(data);
                }
                else {
                    $rootScope.settings.post(['system', 'parameter', 'GetByClassCode'], $scope.csClassCode, function (data) {
                        if (data) {
                            $scope.parameterClass = data.Class;
                            
                            $rootScope.Parameters[$scope.csClassCode] = data;
                            
                            SetText(data);
                        }
                    });
                }
            };

           // init();

           
        }],
        template: function (elem, attrs) {
            var valueField = attrs.csValueField;
            if (!valueField) valueField = "IntId";
            var mode = attrs.csMode;
            if (!mode) mode = "edit";
            
            if (mode == "view")
            {
                return '<label>{{text}}</label>'
            }
            else if (attrs.ngReadonly) {
                return '<label class="form-control-static" name="' + attrs.name + '">{{text}}</label>'
            }
            else {
                return '<select class="form-control" ng-model="csModel" name="' + attrs.name + '" ng-required="{{ngRequired}}" ng-options="option.' + valueField + ' as option.Text for option in data" enable-validate="true" ></select>';
            }
        }
    };
}]);
/*
*  多选过滤器，支持对一个属性用数组进行过滤
*  sample： 
*/
app.filter('filterMultiple', ['$filter', function ($filter) {
    return function (items, keyObj) {
        var filterObj = {
            data: items,
            filteredData: [],
            applyFilter: function (obj, key) {
                var fData = [];
                if (this.filteredData.length == 0)
                    this.filteredData = this.data;
                if (obj) {
                    var fObj = {};
                    if (!angular.isArray(obj)) {
                        fObj[key] = obj;
                        fData = fData.concat($filter('filter')(this.filteredData, fObj));
                    } else if (angular.isArray(obj)) {
                        if (obj.length > 0) {
                            for (var i = 0; i < obj.length; i++) {
                                if (angular.isDefined(obj[i])) {
                                    fObj[key] = obj[i];
                                    fData = fData.concat($filter('filter')(this.filteredData, fObj));
                                }
                            }

                        }
                    }
                    if (fData.length > 0) {
                        this.filteredData = fData;
                    }
                }
            }
        };
        if (keyObj) {
            angular.forEach(keyObj, function (obj, key) {
                filterObj.applyFilter(obj, key);
            });
        }
        return filterObj.filteredData;
    }
}]);

app.directive('csBasePicker', ['$rootScope', '$timeout', '$parse', function ($rootScope, $timeout, $parse) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            csBindValue: '=?csBindValue',
            csOption: '=option'
        },
        link: function ($scope, element, attrs) {
            var defaultOption = { disabled: false, multiple: false, bindType: 'object' };
            angular.extend(defaultOption, $scope.csOption);
            

            $scope.option = defaultOption;

            if (!angular.isDefined($scope.option.multiple)) {
                $scope.option.multiple = false;
            }

            if (!angular.isDefined($scope.option.disabled)) {
                $scope.option.disabled = false;
            }

            var bindKey = $scope.option.bindType == 'key';//单选，绑定Id值


            $scope.item = {
                selecteds: []
            };
            $scope.$watch('ngModel', function () {
                if (bindKey) {
                    if (angular.isDefined($scope.ngModel) && $scope.ngModel != '') {
                        $scope.item.selecteds = [$scope.getObj($scope.ngModel, $scope.csBindValue)];
                    } else {
                        $scope.item.selecteds = [];
                    }
                } else {
                    if (angular.isDefined($scope.ngModel)) {
                        if ($scope.option.multiple && angular.isArray($scope.ngModel)) {
                            $scope.item.selecteds = $scope.ngModel;
                        } else if (angular.isObject($scope.ngModel)) {
                            $scope.item.selecteds = [$scope.ngModel];

                        }
                    }
                }
            });
            if (bindKey) {
                $scope.$watch('csBindValue', function () {
                    if (angular.isDefined($scope.ngModel) && $scope.ngModel != '') {
                        $scope.item.selecteds = [$scope.getObj($scope.ngModel, $scope.csBindValue)];
                    }
                });
            }

            var valueChange = function () {
                if (bindKey) {
                    if (!$scope.option.multiple) {
                        if ($scope.item.selecteds.length > 0) {
                            $scope.ngModel = $scope.option.getKey($scope.item.selecteds[0]);
                            $scope.csBindValue = $scope.option.getText($scope.item.selecteds[0]);
                        } else {
                            $scope.ngModel = '';
                            $scope.csBindValue = '';
                        };
                    }
                } else {
                    if ($scope.option.multiple) {
                        $scope.ngModel = $scope.item.selecteds;
                    } else {
                        if ($scope.item.selecteds.length > 0) {
                            $scope.ngModel = $scope.item.selecteds[0];
                        } else {
                            $scope.ngModel = undefined;
                        }
                    }
                }

                if (attrs.ngChange) {
                    $parse(attrs.ngChange)($scope.$parent);
                }
            };

            $scope.getText = function (select) {
                return $scope.option.getText(select);

            };

            $scope.getObj = function (key, value) {
                return $scope.option.getObj(key, value);
            };


            $scope.selectedRemove = function (select) {
                var index = $scope.item.selecteds.indexOf(select);
                $scope.item.selecteds.splice(index, 1);
                valueChange();
            }

            $scope.openSelect = function () {
                $rootScope.settings.open(
                    $scope.option.modalUrl,
                    null,
                    { title: $scope.option.modalTitle, action: 'select', item: $scope.item, option: $scope.option },
                    function (selecteds) {
                        if ($scope.option.multiple) {
                            angular.forEach(selecteds, function (select) {
                                $scope.item.selecteds.push(select);
                            });

                        } else {
                            $scope.item.selecteds = selecteds;

                        }
                        valueChange();

                    }, function () {

                    }
                );
            };
        },
        controller: ['$rootScope', '$scope', '$http', function ($rootScope, $scope, $http) {

        }],
        templateUrl: './templates/select.html'
    };
}]);

app.directive('csItemPicker', ['$rootScope', '$timeout', '$parse', function ($rootScope, $timeout, $parse) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            csBindValue: '=?csBindValue',
            ngDisabled: '=?ngDisabled',
            csParameters:'='
        },
        link: function ($scope, element, attrs) {
            var code = attrs.csCode;
            
            var parameters = $scope.csParameters;
           
            var multiple = attrs.multiple;
            if (multiple) {
                multiple = multiple.toLowerCase() == 'false' ? false : true
            } else {
                multiple = false;
            }
            var render = function () {
            };
            $scope.option = {
                modalTitle: '选择项目',
                modalUrl: 'System/DataSource/picker',
                multiple: multiple,
                disabled: $scope.ngDisabled,
                bindType: attrs.csBindType,
                code: code,
                parameters : parameters,
                param: $scope.csOption,
                getKey: function (select) {
                    return select.Key;
                },
                getText: function (select) {
                    return select.Value;
                },

                getObj: function (key, value) {
                    return { Key: key, Value: value };
                }
            };

            $scope.selectChange = function () {
                if (attrs.ngChange) {
                    $parse(attrs.ngChange)($scope.$parent);
                }
            };
        },
        template: '<cs-base-picker option="option" ng-model="ngModel" ng-change="selectChange()" cs-bind-value="csBindValue" />'
    };
}]);

/*
*  Picker的select展示形式，使用LookupDataSource数据源绑定，使用下拉框展示，适合于数据量比较小的选取功能，只需要绑定Id字段即可，无需绑定文本字段。
*/
app.directive('csSelectPicker', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            csModel: '=ngModel',
            csCode: '@csCode',
            csView: '@csView',
            csParameters: '@csParameters',
            csReadonly: '=ngReadonly',
            multiple: '=multiple',
            ngRequired: '=ngRequired',
            csContainAllItems: '@csContainAllItems',
        },
        link: function (scope, elem, attrs) {
            scope.csContainAllItems = false;
            if (attrs.csContainAllItems) scope.csContainAllItems = true;
           
        },
        controller: ['$scope', '$http', function ($scope, $http) {
            //$scope.parameterClass = {};
            //$scope.data = [];
            if (!$scope.csView) $scope.csView = "";
            if (!$scope.csParameters) $scope.csParameters = [];
            $scope.text = "";
            var SetText = function (data) {
                var items = data;
                if ($scope.csContainAllItems) {
                    items = angular.copy(data);
                    items.splice(index, 0, { Id: 0, Text: "全部" });
                }

                if ($scope.csModel) {
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].Id === $scope.csModel) {
                            $scope.text = items[i].Text;
                            break;
                        }
                    }
                }
                $scope.data = items;
            };
            $scope.$watch("csModel", function () {
                init();
            })
            var init = function () {
                if (!$rootScope.Datasources) { $rootScope.Datasources = {}; }
                if ($rootScope.Datasources[$scope.csCode]) {
                    var data = $rootScope.Datasources[$scope.csCode];
                    SetText(data);
                }
                else {
                    $rootScope.settings.post(['system', 'datasource', 'GetData'], { Code: $scope.csCode, View: $scope.csView, Parameters: $scope.csParameters }, function (data) {
                        if (data) {
                            $rootScope.Datasources[$scope.csCode] = data;

                            SetText(data);
                        }
                    });
                }
            };

            // init();


        }],
        template: function (elem, attrs) {
            var mode = attrs.csMode;
            if (!mode) mode = "edit";

            if (mode == "view") {
                return '<label>{{text}}</label>'
            }
            else if (attrs.ngReadonly) {
                return '<label class="form-control-static" name="' + attrs.name + '">{{text}}</label>'
            }
            else {
                return '<select class="form-control" ng-model="csModel" name="' + attrs.name + '" ng-required="{{ngRequired}}" ng-options="option.Id as option.Text for option in data" enable-validate="true" ></select>';
            }
        }
    };
}]);

/*
* ng-model : 绑定key值， 多选key值用,分隔
* cs-class : 请求参数数据源
* cs-code, cs-view, cs-parameters ： 请求数据源参数， cs-code无值时请求参数数据源
* cs-contain-all-items ：bool值， 是否包含‘全部’选项
* multiple：bool值， 是否多选
* ng-disabled : bool值表达式， 禁用
*/
app.directive('uiSelectPicker', ['$rootScope', '$parse', function ($rootScope, $parse) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            ngDisabled: '=',
            csParameters : '='
        },
        link: function ($scope, elem, attrs) {
            $scope.name = attrs.name;
            var model = function () {
                if (!angular.isFunction($scope.ngModel)) {
                    if (arguments.length > 0) {
                        $scope.ngModel = arguments[0];
                    }
                    return $scope.ngModel;
                } else {
                    if (arguments.length > 0) {
                        $scope.ngModel(arguments[0]);
                    }
                    return $scope.ngModel();
                }
            };

            var oldValue;
            var destroyCollection = [];

            var code = attrs.csCode;
            var csClass = attrs.csClass;
            var view = attrs.csView;
            var parameters = $scope.csParameters;
            var csContainAllItems = $parse(attrs.csContainAllItems)($scope);
            var multiple = attrs.multiple;
            if (multiple) {
                multiple = multiple.toLowerCase() == 'false' ? false : true
            } else {
                multiple = false;
            }
            $scope.multiple = multiple;

            if (!angular.isDefined(csContainAllItems) || csContainAllItems == null || csContainAllItems == '') {
                csContainAllItems = false;
            }

            var selected;
            if (multiple) {
                selected = [];
            }
            $scope.value = function () {
                if (arguments.length > 0) {
                    if (multiple) {
                        if (angular.isArray(arguments[0])) {
                            selected = arguments[0];
                        } else {
                            selected.push(arguments[0]);
                        }
                        var keys = '';
                        for (var i = 0; i < selected.length; i++) {
                            if (i == selected.length - 1) {
                                keys += selected[i].Key;
                            } else {
                                keys += selected[i].Key + ',';
                            }
                        }
                        oldValue = keys;
                        
                        model(keys);
                    } else {
                        selected = arguments[0];
                        oldValue = arguments[0].Key;
                        
                        model(arguments[0].Key);
                    }
                } else {
                    return selected
                }
            };

            var setByViewValue = function () {
                //避免循环触发数据修改事件
                if (oldValue == model()) {
                    return;
                }
                oldValue = model();

                var defaultKeys = [];
                if (model() && multiple) { //多选ng-model值用，分隔Key
                    defaultKeys = model().toString().split(',');
                }
                if (multiple) {
                    selected = [];
                } else {
                    selected = undefined;
                }
                if (angular.isDefined(model())) {
                    angular.forEach($scope.items, function (item) {
                        if (multiple) {
                            if (defaultKeys.indexOf(item.Key.toString()) >= 0) {
                                selected.push(item);
                            }

                        } else {
                            if (model() == item.Key) {
                                selected = item;
                            }
                        }

                    })
                }
            }

            var init = function () {
                var dataSource = $rootScope.settings.getDataSource();
                var getFun = code ? dataSource.get : dataSource.getParameter;
                getFun(code ? code : csClass, view, parameters).then(function (data) {
                    //$scope.items = data.Data;
                    //$scope.source = data.DataSource;
                    $scope.items = [];
                    if (csContainAllItems) {
                        $scope.items.push({ Key: '', Value: '全部' });
                    }

                    angular.forEach(data.Data, function (d) {
                        var item;
                        if (code) {
                            item = { Key: d[data.DataSource.ValueFieldName], Value: d[data.DataSource.TextFieldName] };
                        } else {
                            item = { Key: d['IntId'], Value: d['Text'] };
                        }
                        $scope.items.push(item);
                    });

                    destroyCollection.push($scope.$watch('ngModel', function () {
                        setByViewValue();
                    }));

                });
            };

            //destroyCollection.push($scope.$watch(attrs.ngDisabled, function (value) {
            //    $scope.disabled = value;
            //}));

            init();

            $scope.$on('$destroy', function () {
                for (var i = 0, ii = destroyCollection.length; i < ii; ++i) {
                    destroyCollection[i]();
                }
            });

        },
        templateUrl: 'templates/uiselectpicker.html'
    };
}]);

/*
* ng-model : 绑定key值， 多选key值用,分隔
* cs-code： 请求数据源参数
* ng-disabled : bool值表达式， 禁用
*/
app.directive('checkboxPicker', ['$rootScope', '$parse', function ($rootScope, $parse) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            ngDisabled: '='
        },
        link: function ($scope, elem, attrs) {

            var model = function () {
                if (!angular.isFunction($scope.ngModel)) {
                    if (arguments.length > 0) {
                        $scope.ngModel = arguments[0];
                    }
                    return $scope.ngModel;
                } else {
                    if (arguments.length > 0) {
                        $scope.ngModel(arguments[0]);
                    }
                    return $scope.ngModel();
                }
            };

            var oldValue;
            var destroyCollection = [];

            var code = attrs.csClass;

            $scope.name = attrs.name;

            $scope.checkedItems = {};

            $scope.checkedChange = function () {
                var keys = '';
                angular.forEach($scope.checkedItems, function (value, key) {
                    if (value) {
                        keys += key + ',';
                    }
                });
                keys = keys.trimStringRight(',');
                oldValue = keys;
                model(keys);
            };

            var setByViewValue = function () {
                //避免循环触发数据修改事件
                if (oldValue == model()) {
                    return;
                }
                oldValue = model();

                var defaultKeys = [];
                if (model()) { //多选ng-model值用，分隔Key
                    defaultKeys = model().toString().split(',');
                }
                $scope.checkedItems = {};
                if (angular.isDefined(model())) {
                    angular.forEach($scope.items, function (item) {
                        if (defaultKeys.indexOf(item.Key.toString()) >= 0) {
                            $scope.checkedItems[item.Key] = true;        
                        }
                    })
                }
            }

            var init = function () {
                var dataSource = $rootScope.settings.getDataSource();
                dataSource.getParameter(code).then(function (data) {
                    //$scope.items = data.Data;
                    //$scope.source = data.DataSource;
                    $scope.items = [];

                    angular.forEach(data.Data, function (d) {
                        var item = { Key: d['IntId'], Value: d['Text'] };
                        $scope.items.push(item);
                    });

                    destroyCollection.push($scope.$watch('ngModel', function () {
                        setByViewValue();
                    }));

                });
            };

            init();

            $scope.$on('$destroy', function () {
                for (var i = 0, ii = destroyCollection.length; i < ii; ++i) {
                    destroyCollection[i]();
                }
            });

        },
        templateUrl: 'templates/checkboxpicker.html'
    };
}]);

/*
* ng-model : 绑定key值， 多选key值用,分隔
* cs-code： 请求数据源参数
* ng-disabled : bool值表达式， 禁用
*/
app.directive('radioPicker', ['$rootScope', '$parse', function ($rootScope, $parse) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            ngDisabled: '='
        },
        link: function ($scope, elem, attrs) {
            $scope.name = attrs.name;
            var code = attrs.csClass;

            var init = function () {
                var dataSource = $rootScope.settings.getDataSource();
                dataSource.getParameter(code).then(function (data) {
                   
                    $scope.items = [];

                    angular.forEach(data.Data, function (d) {
                        var item = { Key: d['IntId'], Value: d['Text'] };
                        $scope.items.push(item);
                    });

                });
            };
            init();

        },
        templateUrl: 'templates/radiopicker.html'
    };
}]);

app.directive('itemForm', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        transclude: true,
        scope: true,
        link:function($scope, elem, attrs){
            $scope.headerTemplateUrl = attrs.header;
            $scope.footerTemplateUrl = attrs.footer;
            $scope.debug = attrs.debug;
        },

        templateUrl: 'templates/form/item-form.html'
    };
}]);
app.directive('listForm', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        transclude: true,
        templateUrl: 'templates/form/list-form.html'
    };
}]);
app.directive('fieldGroup', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        transclude: true,
        scope:{
            title:"@title"
        },
        templateUrl: 'templates/form/field-group.html'
    };
}]);
app.directive('fieldRow', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        transclude: true,
        templateUrl: 'templates/form/field-row.html'
    };
}]);
app.directive('rangeSilder', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        scope: {
            ngModel: '=',
            option:'='
        },
        link: function ($scope, elem, attrs, ctrl) {
            var unwatch = $scope.$watch('option', function () {
                if ($scope.option) {
                    render();
                }
            });
            var render = function () {

                elem.find('input').ionRangeSlider($scope.option);
                
            };
            $scope.$on('$destroy', unwatch);

        },
        template: function (elem, attrs) {
            var html = '<input type="text" ng-model="ngModel" />';
            return html;
        }
    };
}]);
/*
* 参数状态翻译滤镜 支持将参数Id或Id字符串逗号分隔格式的，转换成参数文本 
* 用法 {{item.Status | translateParameter:cs-class}}  
*/
app.filter('translateParameter', ['$rootScope', function ($rootScope) {
    var isWaiting = {};
    var translations = {};
     function filter(intId, classCode) {
        //console.log(" 调用filter：translateParameter|" + intId + classCode);
        var arrayToObject = function (items, keyName) {
            var obj = {};
            angular.forEach(items, function (item, index) {
                obj[item[keyName]] = item;
            });
            return obj;
        };

        var getTranslationValue = function (key) {
            if (translations[classCode]) {
                if (angular.isString(key)) {
                    var tmp = "";
                    angular.forEach(key.split(','), function (item, index) {
                        if (translations[classCode][item]) {
                            if (tmp.length > 0) {
                                tmp += ",";
                            }
                            tmp += translations[classCode][item].Text;
                        }
                        
                    });
                    return tmp;
                }
                else {
                    if (translations[classCode][key]) {
                        return translations[classCode][key].Text;
                    }
                }

            }
            return "";
        };
        var translationValue = "...";
        if (angular.isUndefined(isWaiting[classCode])) isWaiting[classCode] = false;
        if (translations[classCode]) {
            translationValue = getTranslationValue(intId);
        } else {
            if (isWaiting[classCode] === false) {
                
                isWaiting[classCode] = true;
                if (!$rootScope.Parameters) { $rootScope.Parameters = {}; }
                if ($rootScope.Parameters[classCode]) {
                    var data = $rootScope.Parameters[classCode];
                    translations[classCode] = arrayToObject(data.Data, 'IntId')
                    translationValue = getTranslationValue(intId);
                    isWaiting[classCode] = false;
                }
                else {
                    console.log(" 调用filter：translateParameter-获取数据" + classCode);
                    $rootScope.settings.post(['system', 'parameter', 'GetByClassCode'], classCode, function (data) {
                        if (data) {
                            $rootScope.Parameters[classCode] = data;
                            translations[classCode] = arrayToObject(data.Data, 'IntId');
                        }
                        isWaiting[classCode] = false;
                    });
                }
            }
        }
        //console.log(" 调用filter：translateParameter-返回数据" + intId + classCode + ":" + translationValue);
        return translationValue;
    }
     filter.$stateful = true;
     return filter;
}]);

app.filter('sum', function () {
    return function (input, propertyName) {
        if (!angular.isArray(input)) return 0;
        var value = 0;
        angular.forEach(input,(function(item, index) {
              value += item[propertyName];
        }));
        return value;
    }
});

app.filter('periodToMonth', function () {
    return function (period) {
        if (period){
            var date = moment(period, 'YYYYMM');
            if (date) {
                return date.format('YYYY年MM月')
            }
            return period;
        }
        return "";
    }
});

app.directive('portlet', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'E',
        transclude: true,
        scope: {
            title: "@title"
        },
        templateUrl: 'templates/portlet.html'
    };
}]);
